

#include <fstream>
#include <iostream>

#include <xbase/XBaseClient.h>
#include <xbase_utility.hpp>

static const char *table_name = "inmedia";

void dump_data(std::ostream &out, XBaseClient *client)
{
	XBaseCommandScan scan_cmd;
	scan_cmd.set_table_name(table_name);
	scan_cmd.set_row("", "");
	scan_cmd.add_column("*");
	scan_cmd.set_latesttimestamp(0);
	scan_cmd.set_oldesttimestamp(0);
	scan_cmd.set_ttl(0);
	scan_cmd.set_version(0);
	scan_cmd.set_option(0);
	scan_cmd.set_num_row(1024);

	client->scan_open(&scan_cmd);

	std::size_t counter = 0;

	if((! scan_cmd.fail()) && (! scan_cmd.eof()))
	{
		for(client->scan_next(&scan_cmd);
		    (! scan_cmd.fail()) && (! scan_cmd.eof());
		    client->scan_next(&scan_cmd))
		{
			XBaseRecord &record = scan_cmd.record();
			for(XBaseRecord::iterator it = record.begin();
			    it != record.end();
			    ++it)
			{
				const std::string &row_data = it->row();
				const std::string &column_name = it->column();
				const std::string &value_data = it->value();
				
				if(column_name != "gcid:")
				{
					std::cerr << "bad column_name " << column_name << std::endl;
					continue;
				}
				
				std::string cid, peerid, gcid;
				uint64_t filesize;
				//parse_row_data(row_data, cid, peerid);
				if(row_data.size() != (20 + 16))
				{
					std::cerr << "bad row_data " << dump_string_hex(row_data) << std::endl;
					continue;
				}
				cid.assign(row_data.data(), row_data.data() + 20);
				peerid.assign(row_data.data() + 20, row_data.data() + 20 + 16);
				
				//parse_value_data(value_data, gcid, filesize);
				if(value_data.size() != (20 + 8))
				{
				std::cerr << "bad value_data " << dump_string_hex(value_data) << std::endl;
				continue;
				}
				gcid.assign(value_data.data(), value_data.data() + 20);
				filesize = *reinterpret_cast<const uint64_t*>(value_data.data() + 20);
				
				const uint64_t timestamp = it->timestamp();
				out << dump_string_hex(cid) << '\t'
				    << peerid << '\t'
				    << dump_string_hex(gcid) << '\t'
				    << filesize << '\t'
				    << timestamp << std::endl;
				++counter;
			}
		}
	}

	std::cout << counter << " records readed" << std::endl;
	if(scan_cmd.fail())
	{
		std::cerr << "scan failed: "
			  << scan_cmd.errorstr()
			  << std::endl;
	}
	else if(scan_cmd.eof())
	{
		std::cout << "scan success"
			  << std::endl;
	}

	client->scan_close(&scan_cmd);
	if(scan_cmd.fail())
	{
		std::cerr << "scan close failed: "
			  << scan_cmd.errorstr()
			  << std::endl;
	}
}

int main(int argc, char **argv)
{
	if((argc < 3) || (argc > 4))
	{
		std::cout << "imphub_dbp_dump <master_ip> <master_port> [filename]" << std::endl;
		return 0;
	}

	const char *master_ip = argv[1];
	const int master_port = ::atoi(argv[2]);
	const char *filename = NULL;
	if(argc >= 4)
	{
		filename = argv[3];
	}
	const int timeout = 60;

	std::ostream *out = &std::cout;
	if(filename != NULL)
	{
		out = new std::ofstream(filename);
	}

	XBaseClient *client = new XBaseClient(master_ip, master_port);
	client->set_recv_timeout(timeout);
	client->set_send_timeout(timeout);

	const uint64_t t_start = cur_micro_seconds();
	dump_data(*out, client);
	const uint64_t t_end = cur_micro_seconds();

	const uint64_t t_used = t_end - t_start;
	double used = t_used;
	used /= (1000.0 * 1000.0);
	std::cout << "totaly used " << used << " seconds" << std::endl;

	return 0;
}
